package net.cathackers.devel.scmp.auth.impl;

import net.cathackers.devel.scmp.auth.exceptions.ProfileNotFoundException;
import net.cathackers.devel.scmp.auth.exceptions.ProfileAlreadyExistsException;
import net.cathackers.devel.scmp.auth.interfaces.IdentityManager;
import net.cathackers.devel.scmp.auth.interfaces.ProfileSearchInformation;
import net.cathackers.devel.scmp.auth.interfaces.UserProfile;
import net.cathackers.devel.scmp.auth.interfaces.UserProfileField;
import net.cathackers.devel.scmp.chat.backends.MySQLPoolBackend;
import net.cathackers.devel.scmp.config.impl.IdentityManagerDBConfig;
import net.cathackers.devel.scmp.exceptions.*;
import net.cathackers.devel.scmp.factories.SCMPFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;

import java.util.Map;

public class LocalIdentityManager extends MySQLPoolBackend implements
	IdentityManager {

    private static final String CONNECTION_POOL_NAME = "localIdentitypool";
    private static final String CONNECTION_POOL_URI = "jdbc:apache:commons:dbcp:"
	    + CONNECTION_POOL_NAME;
    private IdentityManagerDBConfig configurator_;
    // private Properties props_ = new Properties();
    // private String fileName_;
    private Map<String, UserProfile> userProfilesCache;

    // private Map<UserProfileListField, String[]> listFieldBackendMapping;

    public LocalIdentityManager(IdentityManagerDBConfig configurator) {
	super(configurator, CONNECTION_POOL_NAME, CONNECTION_POOL_URI);
	userProfilesCache = Collections
		.synchronizedMap(new HashMap<String, UserProfile>());
	this.configurator_ = configurator;
	// this.fileName_ = configFileName;
	// setingUp the connections Pool Driver

    }

    public String getField(UserProfile profile, UserProfileField field)
	    throws ProfileNotFoundException, BackendException {
	String returnFieldValue = null;
	ResultSet result = null;

	PreparedStatement statementToExecute = null;
	super.connect();
	Connection connectionToUse = super.getConnection();
	try {
	    statementToExecute = connectionToUse.prepareStatement("SELECT "
		    + field.getFieldName() + " FROM "
		    + configurator_.getTableName() + " WHERE "
		    + UserProfileField.ID.getFieldName() + " = ? LIMIT 1");
	    statementToExecute.setString(1, profile
		    .getFieldValue(UserProfileField.ID));
	    result = statementToExecute.executeQuery();
	    if (!result.next()) {
		throw new ProfileNotFoundException();
	    }
	    returnFieldValue = result.getString(field.getFieldName());
	} catch (SQLException ex) {
	    logger_.error(ex.getMessage());
	} finally {
	    try {
		statementToExecute.close();
		super.disconnect();
	    } catch (SQLException ex) {
		logger_.error(ex.getMessage());
	    }
	}

	return returnFieldValue;
    }

    /*
     * @Override public String[] getListField(UserProfile profile,
     * UserProfileListField field) throws
     * ProfileNotFoundException,BackendConnectException{ ResultSet result =
     * null; String [] retListFieldValue = null; String fieldsToSelect = "";
     * String[] dbFields = listFieldBackendMapping.get(field);
     * 
     * for(String fieldName : dbFields){ if(fieldsToSelect != ""){
     * fieldsToSelect += ", "; } fieldsToSelect += fieldName; }
     * retListFieldValue = new String[dbFields.length]; try{ result =
     * selectStatement
     * (dbConnect(),fieldsToSelect,configurator_.getDBTableName(),
     * profile.getID()); result.next(); for(int i = 0; i < dbFields.length;
     * i++){ retListFieldValue[i] = result.getString(dbFields[i]); } }
     * catch(SQLException e){ getLogger_().error(e.getMessage()); } return
     * retListFieldValue; }
     */

    @Override
    public String addProfile(UserProfile profile)
	    throws ProfileAlreadyExistsException, BackendException {

	Connection connectionToUse = null;
	String returnID = null;
	String insertQueryString = "INSERT INTO "
		+ configurator_.getTableName();
	String queryFieldsNameToUpdate = "";
	String queryFieldsValue = "";
	String[] fieldsNameToUpdate = profile.getAllFieldNames();
	// String[] listFieldsNameToUpdate = profile.getAllListFieldNames();

	for (String fieldName : fieldsNameToUpdate) {
	    if (queryFieldsNameToUpdate != "") {
		queryFieldsNameToUpdate += ", ";
	    }
	    queryFieldsNameToUpdate += UserProfileField.valueOf(fieldName)
		    .getFieldName();
	    if (queryFieldsValue != "") {
		queryFieldsValue += ", ";
	    }
	    queryFieldsValue += "?";

	}
	/*
	 * for(String listFieldName : listFieldsNameToUpdate){ String[]
	 * listFieldValue =
	 * profile.getListFieldValue(UserProfileListField.valueOf
	 * (listFieldName)); String[] dbListFieldMap =
	 * listFieldBackendMapping.get
	 * (UserProfileListField.valueOf(listFieldName)); for(int i = 0; i <
	 * dbListFieldMap.length; i++){ if(queryFieldsNameToUpdate != "("){
	 * queryFieldsNameToUpdate += ", "; } queryFieldsNameToUpdate +=
	 * dbListFieldMap[i];
	 * 
	 * if(queryFieldsValue != "("){ queryFieldsValue += ", "; }
	 * queryFieldsValue += listFieldValue[i]; } }
	 */
	PreparedStatement insertStatement = null;
	try {
	    super.connect();
	    connectionToUse = super.getConnection();
	    insertStatement = connectionToUse
		    .prepareStatement(insertQueryString + "("
			    + queryFieldsNameToUpdate + ") VALUES("
			    + queryFieldsValue + ")");
	    for (int i = 0; i < fieldsNameToUpdate.length; i++) {
		insertStatement.setString(i + 1, profile
			.getFieldValue(UserProfileField
				.valueOf(fieldsNameToUpdate[i])));
	    }
	    insertStatement.executeUpdate();
	    returnID = profile.getID();
	} catch (SQLException e) {

	    logger_.error(e.getMessage());
	    if (e.getErrorCode() == 1062) {
		throw new ProfileAlreadyExistsException();
	    }
	} catch (ProfileNotFoundException e) {

	} finally {
	    try {
		insertStatement.close();
		super.disconnect();
	    } catch (SQLException ex) {
		logger_.error(ex.getMessage());
	    }
	}
	return returnID;
    }

    @Override
    public UserProfile getProfile(String id) {
	UserProfile newUserProfile;
	boolean x = userProfilesCache.containsKey(id);
	if (!x) {
	    newUserProfile = SCMPFactory.getUserProfile(id, this);
	    if (newUserProfile != null) {
		userProfilesCache.put(id, newUserProfile);
	    }
	} else
	    newUserProfile = userProfilesCache.get(id);

	return newUserProfile;
    }

    @Override
    public UserProfile searchForProfile(ProfileSearchInformation info)
	    throws ProfileNotFoundException, BackendException {
	// Strict search
	Connection connectionToUse = null;
	PreparedStatement statementToExecute = null;
	String searchConstrains = "";

	String[] fieldsName = info.getAllFieldNames();
	UserProfile foundUserProfile = null;
	for (String fieldName : fieldsName) {
	    if (searchConstrains != "")
		searchConstrains += " AND ";
	    searchConstrains += UserProfileField.valueOf(fieldName)
		    .getFieldName()
		    + " = ?";
	}
	if (searchConstrains != "") {

	    try {
		super.connect();
		connectionToUse = super.getConnection();
		statementToExecute = connectionToUse.prepareStatement("SELECT "
			+ UserProfileField.ID.getFieldName() + " FROM "
			+ configurator_.getTableName() + " WHERE "
			+ searchConstrains);
		for (int i = 0; i < fieldsName.length; i++) {
		    statementToExecute.setString(i + 1, info
			    .getFieldValue(UserProfileField
				    .valueOf(fieldsName[i])));
		}
		ResultSet result = statementToExecute.executeQuery();
		if (result.next()) {
		    String id = result.getString(UserProfileField.ID
			    .getFieldName());
		    foundUserProfile = this.getProfile(id);
		} else {
		    throw new ProfileNotFoundException();
		}
	    } catch (SQLException e) {
		logger_.error(e.getMessage());

	    } finally {
		try {

		    statementToExecute.close();
		    super.disconnect();
		} catch (SQLException ex) {
		    logger_.error(ex.getMessage());
		}
	    }
	}
	return foundUserProfile;
    }

    @Override
    public boolean updateProfile(UserProfile profile)
	    throws ProfileNotFoundException, BackendException {
	Connection connectionToUse = null;

	String updateQuery = "UPDATE " + configurator_.getTableName();
	String querySets = "";
	Boolean returnResult = false;
	String[] fieldsToUpdate = profile.getAllFieldNames();

	for (String fieldName : fieldsToUpdate) {
	    if (querySets != "") {
		querySets += ", ";
	    }
	    querySets += UserProfileField.valueOf(fieldName).getFieldName()
		    + " = ?";
	}
	/*
	 * String[] listFieldsToUpdate = profile.getAllListFieldNames();
	 * 
	 * for (String listFieldName : listFieldsToUpdate) { String[]
	 * dbFieldsName =
	 * listFieldBackendMapping.get(UserProfileListField.valueOf
	 * (listFieldName)); String[] listFieldValues =
	 * profile.getListFieldValue
	 * (UserProfileListField.valueOf(listFieldName)); for(int i = 0; i <
	 * dbFieldsName.length; i++){ if(querySets != ""){ querySets += ", "; }
	 * querySets += dbFieldsName[i] + " = '" + listFieldValues[i]; }
	 * 
	 * }
	 */
	PreparedStatement updateStatement = null;
	try {
	    super.connect();
	    connectionToUse = super.getConnection();
	    updateStatement = connectionToUse.prepareStatement(updateQuery
		    + " SET " + querySets + " WHERE "
		    + UserProfileField.ID.getFieldName() + " = ?");
	    int i;
	    for (i = 0; i < fieldsToUpdate.length; i++) {
		updateStatement.setString(i + 1, profile
			.getFieldValue(UserProfileField
				.valueOf(fieldsToUpdate[i])));
	    }
	    updateStatement.setString(i + 1, profile.getID());
	    updateStatement.executeUpdate();
	    returnResult = true;
	} catch (SQLException e) {
	    logger_.error(e.getMessage());
	    returnResult = false;
	    throw new ProfileNotFoundException();

	} finally {

	    try {

		updateStatement.close();
		super.disconnect();
	    } catch (SQLException ex) {
		logger_.error(ex.getMessage());
	    }
	}
	return returnResult;
    }

}
